'''
Author: cw
Date: 2025-08-12
Description: http请求工具
'''
import logging
from functools import partial

import asyncio
import requests
import aiohttp


def request(method, url, fmt='json', retry=0, **kwargs):
    '''
        status_code!=200,也希望原样返回
    '''
    ret = None
    try:
        kwargs['headers'] = kwargs.get('headers', {})
        kwargs['timeout'] = kwargs.get('timeout', 5)

        kwargs['headers'].update({
            'User-Agent': 'Mozilla/5.0; mos'
        })

        res = requests.request(
            method.upper(),
            url,
            timeout=kwargs.pop('timeout'),
            **kwargs
        )
        if not (res and res.status_code == requests.codes.ok):
            if retry > 0:
                return request(method, url, fmt, retry - 1, **kwargs)

        # response
        if fmt == 'text':
            res.encoding = 'utf-8'
            ret = res.text
        elif fmt == 'json':
            res.encoding = 'utf-8'
            ret = res.json()
        else:
            ret = res.content
    except Exception as ex:
        if retry > 0:
            return request(method, url, fmt, retry - 1, **kwargs)
        logging.warning(
            f'exception when request, url:{url}, err: {str(ex)}'
        )
    return ret


get = partial(request, 'GET')
post = partial(request, 'POST')
put = partial(request, 'PUT')
delete = partial(request, 'DELETE')
head = partial(request, 'HEAD')


async def aio_request(method, url, fmt='json', retry=1, **kwargs):
    """异步请求"""
    ret = None

    kwargs['timeout'] = kwargs.get('timeout', 60)
    try:
        async with aiohttp.ClientSession() as session:
            async with session.request(method, url, **kwargs) as res:
                ret = await res.read()
                if not (200 <= res.status < 300):
                    if retry > 0:
                        await asyncio.sleep(1)
                        return await aio_request(
                            method, url, fmt, retry - 1, **kwargs)

                    logging.warning(
                        'request fail! url:%s, status:%d, content: %s',
                        url, res.status, ret)

                # response
                if fmt == 'text':
                    ret = await res.text()
                elif fmt == 'json':
                    ret = await res.json()
                else:
                    pass

                return ret
    except Exception as ex:  # pylint: disable=broad-except
        if retry > 0:
            await asyncio.sleep(1)
            return await aio_request(method, url, fmt, retry - 1, **kwargs)

        logging.warning('aio request exception, url:%s, err:%s, type:%s',
                        url, str(ex), type(ex))

    return None

aio_get = partial(aio_request, 'get')
aio_post = partial(aio_request, 'post')
aio_put = partial(aio_request, 'put')
aio_head = partial(aio_request, 'head')
